// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_
#define NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_

#include <string>

#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/strings/string_split.h"
#include "net/http/http_status_code.h"

namespace net {
namespace test_server {

    // Callback called when the response is done being sent.
    using SendCompleteCallback = base::Callback<void(void)>;

    // Callback called when the response is ready to be sent that takes the
    // |response| that is being sent along with the callback |write_done| that is
    // called when the response has been fully written.
    using SendBytesCallback = base::Callback<void(const std::string& response,
        const SendCompleteCallback& write_done)>;

    // Interface for HTTP response implementations.
    class HttpResponse {
    public:
        virtual ~HttpResponse();

        // |send| will send the specified data to the network socket, and invoke
        // |write_done| when complete. When the entire response has been sent,
        // |done| must be called.
        virtual void SendResponse(const SendBytesCallback& send,
            const SendCompleteCallback& done)
            = 0;
    };

    // This class is used to handle basic HTTP responses with commonly used
    // response headers such as "Content-Type". Sends the response immediately.
    class BasicHttpResponse : public HttpResponse {
    public:
        BasicHttpResponse();
        ~BasicHttpResponse() override;

        // The response code.
        HttpStatusCode code() const { return code_; }
        void set_code(HttpStatusCode code) { code_ = code; }

        // The content of the response.
        const std::string& content() const { return content_; }
        void set_content(const std::string& content) { content_ = content; }

        // The content type.
        const std::string& content_type() const { return content_type_; }
        void set_content_type(const std::string& content_type)
        {
            content_type_ = content_type;
        }

        // Adds a custom header.
        void AddCustomHeader(const std::string& key, const std::string& value)
        {
            custom_headers_.push_back(std::make_pair(key, value));
        }

        // Generates and returns a http response string.
        std::string ToResponseString() const;

        void SendResponse(const SendBytesCallback& send,
            const SendCompleteCallback& done) override;

    private:
        HttpStatusCode code_;
        std::string content_;
        std::string content_type_;
        base::StringPairs custom_headers_;

        DISALLOW_COPY_AND_ASSIGN(BasicHttpResponse);
    };

    class RawHttpResponse : public HttpResponse {
    public:
        RawHttpResponse(const std::string& headers, const std::string& contents);
        ~RawHttpResponse() override;

        void SendResponse(const SendBytesCallback& send,
            const SendCompleteCallback& done) override;

        void AddHeader(const std::string& key_value_pair);

    private:
        std::string headers_;
        const std::string contents_;

        DISALLOW_COPY_AND_ASSIGN(RawHttpResponse);
    };

} // namespace test_server
} // namespace net

#endif // NET_TEST_EMBEDDED_TEST_SERVER_HTTP_RESPONSE_H_
